package de.playmee.dialogs;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.Gallery;
import android.widget.ScrollView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import de.playmee.Channel;
import de.playmee.R;
import de.playmee.enums.Mood;
import de.playmee.enums.Release;
import de.playmee.handler.ChannelHandler;
import de.playmee.handler.ChannelTrackRatingHandler;
import de.playmee.views.SimpleGalleryAdapter;

public class EditChannelDialog extends EditDialog {

	private final String TAG = "EditChannelDialog";
	
	private Context context;
	private ChannelHandler cHandler;
	private Channel channel;
	private ChannelTrackRatingHandler ctrHandler;
	private Handler channelViewInitHandler;
	private final int imageSize;
	
	private EditText labelInput;
	
	private Gallery imageInput;
	private View lastImageInGallery;
	
	private final int DURATION_MAX = 1500; // 25s
	private TextView durationText;
	
	private final int BPM_MAX = 1200; // more than 2000 sounds almost like a single note
	private TextView bpmText;
	
	private Set<Release> releases;
	
	private CheckBox considerWeatherInput;
	private CheckBox considerTimeOfDayInput;
	private CheckBox considerSeasonInput;
	
	private final boolean isNewChannel;
	
	private List<Mood> oldMoods;
	private boolean moodsHaveChanged;
	
	public EditChannelDialog(Context context, ChannelHandler cHandler, Channel channel,
			ChannelTrackRatingHandler ctrHandler, Handler channelViewInitHandler,
			int imageSize) {
		super(channel.getMoods());
		this.context = context;
		this.cHandler = cHandler;
		this.channel = channel;
		this.ctrHandler = ctrHandler;
		this.channelViewInitHandler = channelViewInitHandler;
		this.releases = channel.getReleases();
		this.imageSize = imageSize;
		
		isNewChannel = channel.getId() == Channel.NEW_CHANNEL_ID;
		
		// remember the moods
		oldMoods = new ArrayList<Mood>();
		for (Mood mood : channel.getMoods()) {
			oldMoods.add(mood);
		}
		
		create();
	}
	
	/**
	 * creates and sets the dialog
	 */
	private void create() {
		Log.i(TAG, "Creating the dialog...");
		
		ScrollView view = new ScrollView(context);
		LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		inflater.inflate(R.layout.edit_channel, view);
		
		// label
		labelInput = (EditText) view.findViewById(R.id.editLabel);
		labelInput.setText(channel.getLabel());
		
		// image
		final List<Integer> imageIds = new ArrayList<Integer>();
		imageIds.add(R.drawable.ic_contact_picture_2);
		imageIds.add(R.drawable.beach);
		imageIds.add(R.drawable.house);
		imageIds.add(R.drawable.office);
		imageIds.add(R.drawable.running);
		imageIds.add(R.drawable.snowman);
		imageIds.add(R.drawable.party);
		imageIds.add(R.drawable.chill);
		imageIds.add(R.drawable.hard);
		imageIds.add(R.drawable.rock);
		imageIds.add(R.drawable.newest);
		imageIds.add(R.drawable.oldest);
		imageIds.add(R.drawable.romantic);
		imageIds.add(R.drawable.driving);	
		imageInput = (Gallery) view.findViewById(R.id.editImage);
		imageInput.setAdapter(new SimpleGalleryAdapter(context, imageIds, imageSize));
		imageInput.setSpacing(0);
		imageInput.setSelection(imageIds.indexOf(channel.getImage()));
		imageInput.setOnItemSelectedListener(new OnItemSelectedListener() {
			@Override
			public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
				if (lastImageInGallery != null)
					lastImageInGallery.setBackgroundColor(Color.TRANSPARENT);
				lastImageInGallery = view;
				view.setBackgroundColor(Color.WHITE);
				channel.setImage(imageIds.get(position));
			}
			
			@Override
			public void onNothingSelected(AdapterView<?> arg0) {
				// nothing to do
			}
		});
		
		// duration
		durationText = (TextView) view.findViewById(R.id.editDurationText);
		updateDurationText(channel.getDuration());
		SeekBar durationInput = (SeekBar) view.findViewById(R.id.editDurationBar);
		durationInput.setMax(DURATION_MAX);
		durationInput.setProgress(channel.getDuration() / 1000);
		durationInput.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
				// nothing to do
			}
			
			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
				// nothing to do
			}
			
			@Override
			public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
				int duration = progress * 1000; // seconds to milliseconds
				channel.setDuration(duration); 
				updateDurationText(duration);
			}
		});
		
		// bpm
		bpmText = (TextView) view.findViewById(R.id.editBpmText);
		bpmText.setText(channel.getBpm()+"");
		SeekBar bpmInput = (SeekBar) view.findViewById(R.id.editBpmBar);
		bpmInput.setMax(BPM_MAX);
		bpmInput.setProgress(channel.getBpm());
		bpmInput.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
				// nothing to do
			}
			
			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
				// nothing to do
			}
			
			@Override
			public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
				channel.setBpm(progress);
				bpmText.setText(progress+"");
			}
		});
		
		// moods
		CheckBox moodsAngryInput = (CheckBox) view.findViewById(R.id.editMoodsAngry);
		initCheckBox(moodsAngryInput, Mood.Angry);
		CheckBox moodsBoredInput = (CheckBox) view.findViewById(R.id.editMoodsBored);
		initCheckBox(moodsBoredInput, Mood.Bored);
		CheckBox moodsInLoveInput = (CheckBox) view.findViewById(R.id.editMoodsInLove);
		initCheckBox(moodsInLoveInput, Mood.InLove);
		CheckBox moodsEnergeticInput = (CheckBox) view.findViewById(R.id.editMoodsEnergetic);
		initCheckBox(moodsEnergeticInput, Mood.Energetic);
		CheckBox moodsHappyInput = (CheckBox) view.findViewById(R.id.editMoodsHappy);
		initCheckBox(moodsHappyInput, Mood.Happy);
		CheckBox moodsSadInput = (CheckBox) view.findViewById(R.id.editMoodsSad);
		initCheckBox(moodsSadInput, Mood.Sad);
		CheckBox moodsRelaxedInput = (CheckBox) view.findViewById(R.id.editMoodsRelaxed);
		initCheckBox(moodsRelaxedInput, Mood.Relaxed);
		CheckBox moodsStressedInput = (CheckBox) view.findViewById(R.id.editMoodsStressed);
		initCheckBox(moodsStressedInput, Mood.Stressed);
		
		// releases
		CheckBox releasesUntil70sInput = (CheckBox) view.findViewById(R.id.editReleasesUntil70s);
		initCheckBox(releasesUntil70sInput, Release.UntilSeventies);
		CheckBox releases80sInput = (CheckBox) view.findViewById(R.id.editReleases80s);
		initCheckBox(releases80sInput, Release.Eighties);
		CheckBox releases90sInput = (CheckBox) view.findViewById(R.id.editReleases90s);
		initCheckBox(releases90sInput, Release.Nineties);
		CheckBox releasesFrom2kInput = (CheckBox) view.findViewById(R.id.editReleasesFrom2k);
		initCheckBox(releasesFrom2kInput, Release.From2k);
		CheckBox releasesLastYearInput = (CheckBox) view.findViewById(R.id.editReleasesLastYear);
		initCheckBox(releasesLastYearInput, Release.LastYear);
		CheckBox releasesThisYearInput = (CheckBox) view.findViewById(R.id.editReleasesThisYear);
		initCheckBox(releasesThisYearInput, Release.ThisYear);
		
		// consider weather conditions
		considerWeatherInput = (CheckBox) view.findViewById(R.id.editConsiderWeather);
		considerWeatherInput.setChecked(channel.isConsideringWeather());
		considerWeatherInput.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				channel.considerWeather(isChecked);
			}
		});
		
		// consider time of day
		considerTimeOfDayInput = (CheckBox) view.findViewById(R.id.editConsiderTimeOfDay);
		considerTimeOfDayInput.setChecked(channel.isConsideringTimeOfDay());
		considerTimeOfDayInput.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				channel.considerTimeOfDay(isChecked);
			}
		});
		
		// consider season
		considerSeasonInput = (CheckBox) view.findViewById(R.id.editConsiderSeason);
		considerSeasonInput.setChecked(channel.isConsideringSeason());
		considerSeasonInput.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				channel.considerSeason(isChecked);
			}
		});
		
		// create the dialog
		AlertDialog.Builder builder = new AlertDialog.Builder(context);
		builder.setCancelable(false);
		builder.setIcon(android.R.drawable.ic_menu_edit);
		builder.setTitle(channel.getLabel());

		builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// only store new label if it is not empty
				String label = labelInput.getText().toString().trim();
				if (!label.isEmpty()) {
					channel.setLabel(label);
				}
				
				// store channel with new attributes
				if (isNewChannel){ 
					cHandler.insertChannel(channel, true);
				}
				else {
					cHandler.updateChannel(channel);
				}
				
				// reset implicit ratings if moods have changed
				moodsHaveChanged = false;
				if (oldMoods.size() != channel.getMoods().size()) {
					moodsHaveChanged = true;
				} 
				if (!moodsHaveChanged) {
					// check old moods
					for (Mood m : oldMoods) {
						if (!channel.getMoods().contains(m)) {
							moodsHaveChanged = true;
							break;
						}
					}
				}
				if (!moodsHaveChanged) {
					// check new moods
					for (Mood m : channel.getMoods()) {
						if (!oldMoods.contains(m)) {
							moodsHaveChanged = true;
							break;
						}
					}
				}
				if (moodsHaveChanged)
					ctrHandler.reset(channel.getId());
				
				// reload channel view (label may have changed)
				channelViewInitHandler.sendEmptyMessage(0);
			}
		});
		
		builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// nothing to do
			}
		});
		
		builder.setView(view);
		setDialog(builder.create());
	}
	
	/**
	 * updates the text view to display the chosen duration
	 * 
	 * @param duration
	 */
	private void updateDurationText(int duration) {
		int min = (duration / 1000) / 60;
		int sec = (duration / 1000) % 60;
		String minText = min < 10 ? "0"+min : ""+min;
		String secText = sec < 10 ? "0"+sec : ""+sec;
		durationText.setText(minText + ":" + secText + " min");
	}
	
	/**
	 * initializes a checkbox
	 * 
	 * @param checkBox
	 * @param release
	 */
	private void initCheckBox(CheckBox checkBox, final Release release) {
		checkBox.setText(release.toString());
		checkBox.setChecked(releases.contains(release));
		checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				if (isChecked) {
					releases.add(release);
				} else {
					releases.remove(release);
				}
			}
		});
	}
}
